package Game;

import javax.media.opengl.GL2;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.glu.GLUquadric;

import Physics.CollisionSphere;
import Physics.Matrix3;
import Physics.RigidBody;

public class Sphere extends CollisionSphere implements IGameObject 
{
	////////////////////////////
	// Member variables
	////////////////////////////
	private ObjectType		m_objectType = ObjectType.OBJECT_DEFAULTSPHERE;
	private int				m_health = 100;
	private ObjectMaterial 	m_material = ObjectMaterial.DEFAULT;
	private	boolean			m_setToRed = false;
	private boolean			m_showHealth = false;
	
	// for multishots. 3 different spheres to
	// create and register with the physics engine
	// when fired
	Sphere					m_multi1 = null;
	Sphere					m_multi2 = null;
	Sphere					m_multi3 = null;
	
	float					m_scale = 0.0f;
	
	////////////////////////////
	// Member functions
	////////////////////////////
	Sphere(float radius, ObjectMaterial material, ObjectType type)
	{
		m_showHealth = false;
		m_objectType = type;
		
		// collisionsphere value
		m_body = new RigidBody();
		
		m_health = 100;
		m_material = material;
		
		m_multi1 = null;
		m_multi2 = null;
		m_multi3 = null;
		
		m_setToRed = false;
		
		// collisionsphere value
		m_radius = radius;
		
		// collisionsphere value
		float mass = 4.0f * 0.3333f * 3.1415f * radius * radius * radius * ObjectData.getDensity(m_material);
		m_body.setMass(mass);
		
		Matrix3 tensor = new Matrix3();
		float coeff = 0.4f * mass * radius * radius;
		tensor.setInertiaTensorCoeffs(coeff, coeff, coeff);
		m_body.setInertiaTensor(tensor);
		
		m_body.setDamping(0.9f, 0.4f);
		m_body.setAwake(true);
		m_body.setMaterial(m_material);
		
		float scale = 1.0f;
		
		switch(m_objectType)
		{
		case WEAPON_NORMAL:
			scale = ObjectData.COCONUT_SCALE;
			break;
			
		case WEAPON_MULTI:
			scale = ObjectData.MULTINUT_SCALE;
			m_multi1 = new Sphere(radius * ObjectData.COMPONENTNUT_FACTOR, ObjectMaterial.DEFAULT, ObjectType.WEAPON_NORMAL);
			m_multi2 = new Sphere(radius * ObjectData.COMPONENTNUT_FACTOR, ObjectMaterial.DEFAULT, ObjectType.WEAPON_NORMAL);
			m_multi3 = new Sphere(radius * ObjectData.COMPONENTNUT_FACTOR, ObjectMaterial.DEFAULT, ObjectType.WEAPON_NORMAL);
			break;
			
		case WEAPON_ROCKET:
			scale = ObjectData.ROCKETNUT_SCALE;
			break;
			
		case WEAPON_EXPLODE:
			scale = ObjectData.EXPLODENUT_SCALE;
			break;
			
		case BIRD_BLACKBIRD:
			scale = ObjectData.BLACKBIRD_SCALE;
			break;
			
		case BIRD_SEAGULL:
			scale = ObjectData.SEAGULL_SCALE;
			break;
			
		case BIRD_PARROT:
			scale = ObjectData.PARROT_SCALE;
			break;
			
		case BIRD_TOUCAN:
			scale = ObjectData.TOUCAN_SCALE;
			break;
			
		case OBJECT_CATAPULT:
			scale = ObjectData.CATAPULT_SCALE;
			break;
			
		case OBJECT_STONESPHERE:
			scale = radius;
			break;
			
		default:
			scale = ObjectData.COCONUT_SCALE;
			break;		
		
		}
		
		
		scale *= (radius / ObjectData.SPHERE_DEFAULTRADIUS);
		
		// use this as a temporary hack
		m_scale = scale;
		
		// TODO: create the JOGL scaling matrix here
		// Create equivalent to:
		//D3DXMatrixScaling(&mScale, scale, scale, scale);
		
		// TODO: Create coloring material here?
		// Create equivalent to:
		//mMtrl = Mtrl(WHITE*0.8f, WHITE, WHITE*0.8f, 8.0f);
		
		
	}
	
	
	public void update(float dt)
	{
		// not needed. All updates are done through the 
		// rigid body object that this class inherits from
		// and all function calls are handled by the game.
		
	}
	
	////////////////////////////
	// IGameObject overrides
	////////////////////////////
	@Override
	public void render(GL2 gl, GLU glu) 
	{
		gl.glPushMatrix();
		gl.glTranslatef(m_body.getPosition().x, m_body.getPosition().y, 0);
		
		 
		// Prepare light parameters.
        float SHINE_ALL_DIRECTIONS = 1;
        float[] lightPos = {-30, 0, 0, SHINE_ALL_DIRECTIONS};
        float[] lightColorAmbient = {0.2f, 0.2f, 0.2f, 1f};
        float[] lightColorSpecular = {0.8f, 0.8f, 0.8f, 1f};

        // Set light parameters.
        gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_POSITION, lightPos, 0);
        gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_AMBIENT, lightColorAmbient, 0);
        gl.glLightfv(GL2.GL_LIGHT1, GL2.GL_SPECULAR, lightColorSpecular, 0);

        // Enable lighting in GL.
        gl.glEnable(GL2.GL_LIGHT1);
        gl.glEnable(GL2.GL_LIGHTING);

        // Set material properties.
        float[] rgba = {1f, 1f, 1f};
        gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_AMBIENT, rgba, 0);
        gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_SPECULAR, rgba, 0);
        gl.glMaterialf(GL2.GL_FRONT, GL2.GL_SHININESS, 0.5f);
        
        
        // draw the sphere
        //gl.glColor3f(0.3f, 0.5f, 1f);
        GLUquadric earth = glu.gluNewQuadric();
        glu.gluQuadricTexture(earth, true);
        glu.gluQuadricDrawStyle(earth, GLU.GLU_FILL);
        glu.gluQuadricNormals(earth, GLU.GLU_FLAT);
        glu.gluQuadricOrientation(earth, GLU.GLU_OUTSIDE);
        final float radius = m_scale*30;
        final int slices = 16;
        final int stacks = 16;
        glu.gluSphere(earth, radius, slices, stacks);
        glu.gluDeleteQuadric(earth);
        gl.glPopMatrix();
		
	}
	
	@Override
	public RigidBody getBody() 
	{
		return m_body;
	}
	
	@Override
	public ObjectMaterial getMaterial() 
	{
		return m_material;
	}
	
	@Override
	public void specialAbility(FuriousTourist game) 
	{
		// do nothing for now.
	}
	
	@Override
	public void specialAbility2() 
	{
		// for exploding coconuts to turn red before exploding.
		m_setToRed = true;
	}

	@Override
	public int getType() 
	{
		return 0;
	}

	@Override
	public int getHP() 
	{
		return m_health;
	}

	@Override
	public void setHP(int hp) 
	{
		m_health = hp;
	}

	@Override
	public boolean hasHealth() 
	{
		switch(m_objectType)
		{
		case WEAPON_NORMAL:
		case WEAPON_MULTI:
		case WEAPON_ROCKET:
		case WEAPON_EXPLODE:
		case OBJECT_CATAPULT:
			return false;
		
		default:
			return true;
		}
	}

	@Override
	public void toggleShowHealth() 
	{
		if (hasHealth())
		{
			m_showHealth = !m_showHealth;
		}
	}

}
